#include <audio/PianoKeyboard.h>

namespace ne
{
    const uint32_t PianoKeyboard::KEYBOARD_KEYS_NUM = 88;
    const uint32_t PianoKeyboard::MIN_KEYBOARD_KEY = uint32_t(MIDI_A0);
    const uint32_t PianoKeyboard::MAX_KEYBOARD_KEY = uint32_t(MIDI_C8);
    const uint32_t PianoKeyboard::OCTAVE_KEYS = 12;
    const uint32_t PianoKeyboard::BLACK_KEYS_NUM = 5;
    const uint32_t PianoKeyboard::WHITE_KEYS_NUM = 7;
    const uint32_t PianoKeyboard::BLACK_KEYS[BLACK_KEYS_NUM] = {1, 3, 6, 8, 10};
    const uint32_t PianoKeyboard::WHITE_KEYS[WHITE_KEYS_NUM] = {0, 2, 4, 5, 7, 9, 11};
    
    PianoKeyboard::PianoKeyboard()
    {
        reset();
    }

    void PianoKeyboard::setKeyUp(const MIDIPitchType key)
    {
        if (IsPianoKey(key))
        {
            mKeysDown[uint32_t(key) - MIN_KEYBOARD_KEY] = false;
        }
    }

    bool PianoKeyboard::isKeyUp(const MIDIPitchType key) const
    {
        if (IsPianoKey(key))
        {
            return !mKeysDown[uint32_t(key) - MIN_KEYBOARD_KEY];
        }
        return false;
    }

    void PianoKeyboard::setKeyDown(const MIDIPitchType key)
    {
        if (IsPianoKey(key))
        {
            mKeysDown[uint32_t(key) - MIN_KEYBOARD_KEY] = true;
        }
    }

    bool PianoKeyboard::isKeyDown(const MIDIPitchType key) const
    {
        if (IsPianoKey(key))
        {
            return mKeysDown[uint32_t(key) - MIN_KEYBOARD_KEY];
        }
        return false;
    }

    void PianoKeyboard::reset()
    {
        for (uint32_t i=0; i<KEYBOARD_KEYS_NUM; ++i)
        {
            mKeysDown[i] = false;
        }
    }

    PianoKeyboard::~PianoKeyboard()
    {
    }

    bool PianoKeyboard::IsPianoKey(const MIDIPitchType key)
    {
        return (MIN_KEYBOARD_KEY <= uint32_t(key) &&
                uint32_t(key) <= MAX_KEYBOARD_KEY);
    }
    
    bool PianoKeyboard::IsBlackKey(const MIDIPitchType key)
    {
        uint32_t m = uint32_t(key) % OCTAVE_KEYS;
        for (uint32_t i=0; i<BLACK_KEYS_NUM; ++i)
        {
            if (m == BLACK_KEYS[i])
            {
                return true;
            }
        }
        return false;
    }

    bool PianoKeyboard::IsWhiteKey(const MIDIPitchType key)
    {
        uint32_t m = key % OCTAVE_KEYS;
        for (uint32_t i=0; i<BLACK_KEYS_NUM; ++i)
        {
            if (m == BLACK_KEYS[i])
            {
                return false;
            }
        }
        return true;
    }

}
